Skip to content

Create hls-export-plugin with Export '...' code action#4952

Merged
crtschin merged 11 commits into
haskell:masterfrom
crtschin:crtschin/export-1-export
Jun 18, 2026
Merged

Create hls-export-plugin with Export '...' code action#4952
crtschin merged 11 commits into
haskell:masterfrom
crtschin:crtschin/export-1-export

Conversation

@crtschin

@crtschin crtschin commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

First part to #4948.

This differs from the existing action that hls-refactor-plugin provided:

  • hls-refactor-plugin only worked when the symbol was detected unused.
  • This uses structured diagnostics
  • Handles constructor/types nicely
  • Uses ghc-exactprint for export splicing

@crtschin crtschin force-pushed the crtschin/export-1-export branch 3 times, most recently from 418edd5 to e9a5ab3 Compare June 8, 2026 21:11
@crtschin crtschin marked this pull request as ready for review June 9, 2026 20:10
@fendor fendor added the status: needs review This PR is ready for review label Jun 10, 2026
@noughtmare

Copy link
Copy Markdown
Contributor

I've tried this PR with GHC for #4967. This PR indeed fixes the invalid syntax problem, but unfortunately it does expand CPP macros in the export list. That file uses this macro in its export list:

#include "primop-vector-tys-exports.hs-incl"

@crtschin

Copy link
Copy Markdown
Collaborator Author

This PR indeed fixes the invalid syntax problem, but unfortunately it does expand CPP macros in the export list. That file uses this macro in its export list:

Thanks for testing this out!

That's an interesting wrinkle, I believe HLS generally works with post-preprocessor sources. So I'd have to build something to specifically work with preprocessor directives. I won't do that here, as the PR is already quite large, but I'll note it in #4948.

@crtschin

Copy link
Copy Markdown
Collaborator Author

I won't do that here, as the PR is already quite large...

For the curious, I now have a patch locally for this, but I'll refrain from making a PR until this is merged, as there isn't a nice way to do stacked PRs on GH (yet).

@fendor fendor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome patch, thank you very much! I have a couple of small notes and suggestions.

@@ -0,0 +1,283 @@
{-# LANGUAGE CPP #-}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parts of this module might fit well into hls-exactprint-utils as well

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll defer this until other plugins start touching the export list. These would have only one consumer in the export plugin.

Comment on lines +71 to +78
#if MIN_VERSION_ghc(9,8,0)
isUnusedTopBind d =
case d ^? fdStructuredMessageL . _SomeStructuredMessage . msgEnvelopeErrorL . _TcRnMessage of
Just (TcRnUnusedName _ UnusedNameTopDecl) -> True
_ -> False
#else
isUnusedTopBind _ = False
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This CPP could be avoided (or pushed to another place) by introducing a pattern synonym for TcRnUnusedName in Compat.Error. In that pattern synonym, you use the CPP to make sure it can't be mached on older GHC versions.

Edit: Or introduce another prism _TcRnUnusedName that won't ever match on older GHC versions

Comment thread plugins/hls-export-plugin/test/Main.hs Outdated
Comment on lines +19 to +21
runExport :: (FilePath -> Session a) -> IO a
runExport act =
runSessionWithTestConfig def

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I like pushing the testCase label into the plugin specific test runner, e.g.

Suggested change
runExport :: (FilePath -> Session a) -> IO a
runExport act =
runSessionWithTestConfig def
runExport :: String -> (FilePath -> Session a) -> IO a
runExport label act =
testCase label $ runSessionWithTestConfig def

But that's just my opinion, this is fine as well.

@@ -0,0 +1,15 @@
cradle:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a cradle can lead to flaky tests as the test session compiles all test modules in each test. Waiting for progress done, or waiting for a specific diagnostic, can sometimes then be signalled from the wrong source file.

Not a blocker, but generally we prefer to use the test helpers that copy the sources individually into temporary directories for better isolation.
Also, this layout might have issues with your work on #4364, as they would be sharing build directories.

@fendor fendor removed the status: needs review This PR is ready for review label Jun 18, 2026
crtschin added 11 commits June 19, 2026 00:06
A shared library lets the export plugin reuse them without depending on
hls-refactor-plugin.
Offered on `-Wunused-top-binds` diagnostics.
The hls-export-plugin Export action replaces it.
Freshly built names carry EpAnnNotUsed before GHC 9.9, so addParens
could not parenthesize operators.
TcRnUnusedName gained structured provenance only in GHC 9.8, so 9.6
cannot identify unused top-level binds to attach the action to.
@crtschin crtschin force-pushed the crtschin/export-1-export branch from e9a5ab3 to d498988 Compare June 18, 2026 22:06
@crtschin crtschin requested a review from wz1000 as a code owner June 18, 2026 22:06
@crtschin crtschin enabled auto-merge (squash) June 18, 2026 22:25
@crtschin crtschin merged commit 14bbc35 into haskell:master Jun 18, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants